package me.amiee.nicetab.library;

import ohos.aafwk.ability.AbilitySlice;
import ohos.agp.colors.RgbColor;
import ohos.agp.components.*;
import ohos.agp.components.element.ShapeElement;
import ohos.agp.render.Canvas;
import ohos.agp.render.Paint;
import ohos.agp.render.Path;
import ohos.agp.text.Font;
import ohos.agp.utils.Color;
import ohos.agp.utils.Point;
import ohos.agp.utils.Rect;
import ohos.agp.utils.RectFloat;
import ohos.app.Context;
import ohos.utils.PlainArray;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

/* * 滑动TabLayout,对于ViewPager的依赖性强 */
public class NiceTabLayout extends PositionLayout implements PageSlider.PageChangedListener {
    private Context mContext;
    private PageSlider mViewPager;
    private List<SamplePagerItem> mTables;
    private DirectionalLayout mTabsContainer;
    private int mCurrentTab;
    private float mCurrentPositionOffset;
    private int mCurrentOffset;
    private int mTabCount;
    /* * 用于绘制显示器 */
    private Rect mIndicatorRect = new Rect();
    /* * 用于实现滚动居中 */
    private Rect mTabRect = new Rect();

    private Paint mIndicatorDrawable = new Paint();

    private Paint mRectPaint = new Paint();
    private Paint mDividerPaint = new Paint();
    private Paint mTrianglePaint = new Paint();
    private Path mTrianglePath = new Path();
    public static final int STYLE_NORMAL = 0;
    public static final int STYLE_TRIANGLE = 1;
    public static final int STYLE_BLOCK = 2;
    private int mIndicatorStyle = STYLE_NORMAL;

    public static final int GRAVITY_TOP = 0;
    public static final int GRAVITY_BOTTOM = 1;
    public static final int GRAVITY_LEFT = 2;
    public static final int GRAVITY_RIGHT = 3;

    private float mTabPadding;
    private boolean mTabSpaceEqual;
    private float mTabWidth;

    /* * indicator */
    private int mIndicatorColor;

    private float mIndicatorHeight;
    private float mIndicatorWidth;
    private float mIndicatorCornerRadius;
    private float mIndicatorMarginLeft;
    private float mIndicatorMarginTop;
    private float mIndicatorMarginRight;
    private float mIndicatorMarginBottom;
    private int mIndicatorGravity;
    private boolean mIndicatorWidthEqualTitle;

    /* * underline */
    private int mUnderlineColor;

    private float mUnderlineHeight;
    private int mUnderlineGravity;

    /* * divider */
    private int mDividerColor;

    private float mDividerWidth;
    private float mDividerPadding;

    /* * title */
    public static final int TEXT_BOLD_NONE = 0;

    public static final int TEXT_BOLD_WHEN_SELECT = 1;
    public static final int TEXT_BOLD_BOTH = 2;
    private float mTextsize;
    private int mTextSelectColor;
    private int mTextUnselectColor;
    private int mTextBold;
    private boolean mTextAllCaps;

    private int mLastScrollX;
    private boolean mSnapOnTabClick;

    private ScrollView scrollView;

    private int mTargetIndex = 0;
    private SHOWTYPE showtype=SHOWTYPE.IconAndTitle;
    private SCROLLCHOOSETYPE scrollchoosetype=SCROLLCHOOSETYPE.Center;
    private FONTTYPE fonttype=FONTTYPE.OHOS;

    public NiceTabLayout(Context context) {
        this(context, null, null);
    }

    public NiceTabLayout(Context context, AttrSet attrs) {
        this(context, attrs, null);
    }

    public NiceTabLayout(Context context, AttrSet attrs, String defStyleAttr) {
        super(context, attrs, defStyleAttr);
        setClipEnabled(false);

        this.mContext = context;

        mTabsContainer = new DirectionalLayout(context);
        mTabsContainer.setWidth(LayoutConfig.MATCH_CONTENT);
        mTabsContainer.setHeight(LayoutConfig.MATCH_CONTENT);
        mTabsContainer.setOrientation(Component.HORIZONTAL);
        addComponent(mTabsContainer);

        initPaint();

        mIndicatorStyle = AttrUtils.getIntFromAttr(attrs, "tl_indicator_style", STYLE_NORMAL);
        mIndicatorColor =
                AttrUtils.getColorFromAttr(
                        attrs, "tl_indicator_color", mIndicatorStyle == STYLE_BLOCK ? 0xff4B6A87 : 0xffffffff);
        mIndicatorHeight =
                AttrUtils.getDimensionFromAttr(
                        attrs,
                        "tl_indicator_height",
                        dp2px(mIndicatorStyle == STYLE_TRIANGLE ? 4 : (mIndicatorStyle == STYLE_BLOCK ? -1 : 2)));
        mIndicatorWidth =
                AttrUtils.getDimensionFromAttr(
                        attrs, "tl_indicator_width", dp2px(mIndicatorStyle == STYLE_TRIANGLE ? 10 : -1));
        mIndicatorCornerRadius =
                AttrUtils.getDimensionFromAttr(
                        attrs, "tl_indicator_corner_radius", dp2px(mIndicatorStyle == STYLE_BLOCK ? -1 : 0));
        mIndicatorMarginLeft = AttrUtils.getDimensionFromAttr(attrs, "tl_indicator_margin_left", dp2px(0));
        mIndicatorMarginTop =
                AttrUtils.getDimensionFromAttr(
                        attrs, "tl_indicator_margin_top", dp2px(mIndicatorStyle == STYLE_BLOCK ? 7 : 0));
        mIndicatorMarginRight = AttrUtils.getDimensionFromAttr(attrs, "tl_indicator_margin_right", dp2px(0));
        mIndicatorMarginBottom =
                AttrUtils.getDimensionFromAttr(
                        attrs, "tl_indicator_margin_bottom", dp2px(mIndicatorStyle == STYLE_BLOCK ? 7 : 0));
        mIndicatorGravity = AttrUtils.getIntFromAttr(attrs, "tl_indicator_gravity", GRAVITY_BOTTOM);
        mIndicatorWidthEqualTitle = AttrUtils.getBooleanFromAttr(attrs, "tl_indicator_width_equal_title", false);

        mUnderlineColor = AttrUtils.getColorFromAttr(attrs, "tl_underline_color", 0xffffffff);
        mUnderlineHeight = AttrUtils.getDimensionFromAttr(attrs, "tl_underline_height", dp2px(0));
        mUnderlineGravity = AttrUtils.getIntFromAttr(attrs, "tl_underline_gravity", GRAVITY_BOTTOM);

        mDividerColor = AttrUtils.getColorFromAttr(attrs, "tl_divider_color", 0xffffffff);
        mDividerWidth = AttrUtils.getDimensionFromAttr(attrs, "tl_divider_width", dp2px(0));
        mDividerPadding = AttrUtils.getDimensionFromAttr(attrs, "tl_divider_padding", dp2px(12));

        mTextsize = AttrUtils.getDimensionFromAttr(attrs, "tl_textsize", sp2px(14));
        mTextSelectColor = AttrUtils.getColorFromAttr(attrs, "tl_textSelectColor", 0xffffffff);
        mTextUnselectColor = AttrUtils.getColorFromAttr(attrs, "tl_textUnselectColor", 0xaaffffff);
        mTextBold = AttrUtils.getIntFromAttr(attrs, "tl_textBold", TEXT_BOLD_NONE);
        mTextAllCaps = AttrUtils.getBooleanFromAttr(attrs, "tl_textAllCaps", false);

        mTabSpaceEqual = AttrUtils.getBooleanFromAttr(attrs, "tl_tab_space_equal", false);
        mTabWidth = AttrUtils.getDimensionFromAttr(attrs, "tl_tab_width", dp2px(-1));
        mTabPadding =
                AttrUtils.getDimensionFromAttr(
                        attrs, "tl_tab_padding", mTabSpaceEqual || mTabWidth > 0 ? dp2px(0) : dp2px(20));

        onDraw();
    }
    public enum SHOWTYPE{
        Icon,Title,IconAndTitle
    }
    public enum SCROLLCHOOSETYPE{
        Left,Center
    }

    public enum FONTTYPE{
        OHOS,Ios
    }
    public void setScrollchoosetype(SCROLLCHOOSETYPE scrollchoosetype) {
        this.scrollchoosetype = scrollchoosetype;
    }

    public void setShowtype(SHOWTYPE showtype) {
        this.showtype = showtype;
        updateTabStyles();
    }

    public void setFonttype(FONTTYPE fonttype) {
        this.fonttype = fonttype;
        updateTabStyles();
    }

    public static class SlidingTabLayoutConfig {
        public Integer indicatorStyle;
        public Integer indicatorColor;
        public Integer indicatorHeight;
        public Integer indicatorWidth;
        public Integer indicatorCornerRadius;
        public Integer indicatorMarginLeft;
        public Integer indicatorMarginTop;
        public Integer indicatorMarginRight;
        public Integer indicatorMarginBottom;
        public Integer indicatorGravity;
        public Boolean indicatorWidthEqualTitle;

        public Integer underlineColor;
        public Integer underlineHeight;
        public Integer underlineGravity;

        public Integer dividerColor;
        public Integer dividerWidth;
        public Integer dividerPadding;

        public Integer textsize;
        public Integer textSelectColor;
        public Integer textUnselectColor;
        public Integer textBold;
        public Boolean textAllCaps;

        public Boolean tabSpaceEqual;
        public Integer tabWidth;
        public Integer tabPadding;
    }

    public void initPaint() {
        mRectPaint.setAntiAlias(true);
        mDividerPaint.setAntiAlias(true);
        mTrianglePaint.setAntiAlias(true);
        mTextPaint.setAntiAlias(true);
    }

    public void setScrollView(ScrollView scrollView) {
        this.scrollView = scrollView;
    }

    public void setConfig(SlidingTabLayoutConfig config) {
        if (config.indicatorStyle != null) {
            mIndicatorStyle = config.indicatorStyle;
            mIndicatorColor = mIndicatorStyle == STYLE_BLOCK ? 0xff4B6A87 : 0xffffffff;
            mIndicatorHeight = dp2px(mIndicatorStyle == STYLE_TRIANGLE ? 4 : (mIndicatorStyle == STYLE_BLOCK ? -1 : 2));
            mIndicatorWidth = dp2px(mIndicatorStyle == STYLE_TRIANGLE ? 10 : -1);
            mIndicatorCornerRadius = dp2px(mIndicatorStyle == STYLE_BLOCK ? -1 : 0);
            mIndicatorMarginLeft = dp2px(0);
            mIndicatorMarginTop = dp2px(mIndicatorStyle == STYLE_BLOCK ? 7 : 0);
            mIndicatorMarginRight = dp2px(0);
            mIndicatorMarginBottom = dp2px(mIndicatorStyle == STYLE_BLOCK ? 7 : 0);
        }
        if (config.indicatorColor != null) {
            mIndicatorColor = config.indicatorColor;
        }
        if (config.indicatorHeight != null) {
            mIndicatorHeight = dp2px(config.indicatorHeight);
        }
        if (config.indicatorWidth != null) {
            mIndicatorWidth = dp2px(config.indicatorWidth);
        }
        if (config.indicatorCornerRadius != null) {
            mIndicatorCornerRadius = dp2px(config.indicatorCornerRadius);
        }
        if (config.indicatorMarginLeft != null) {
            mIndicatorMarginLeft = dp2px(config.indicatorMarginLeft);
        }
        if (config.indicatorMarginTop != null) {
            mIndicatorMarginTop = dp2px(config.indicatorMarginTop);
        }
        if (config.indicatorMarginRight != null) {
            mIndicatorMarginRight = dp2px(config.indicatorMarginRight);
        }
        if (config.indicatorMarginBottom != null) {
            mIndicatorMarginBottom = dp2px(config.indicatorMarginBottom);
        }
        if (config.indicatorGravity != null) {
            mIndicatorGravity = config.indicatorGravity;
        }
        if (config.indicatorWidthEqualTitle != null) {
            mIndicatorWidthEqualTitle = config.indicatorWidthEqualTitle;
        }
        if (config.underlineColor != null) {
            mUnderlineColor = config.underlineColor;
        }
        if (config.underlineHeight != null) {
            mUnderlineHeight = dp2px(config.underlineHeight);
        }
        if (config.underlineGravity != null) {
            mUnderlineGravity = config.underlineGravity;
        }

        if (config.dividerColor != null) {
            mDividerColor = config.dividerColor;
        }
        if (config.dividerWidth != null) {
            mDividerWidth = dp2px(config.dividerWidth);
        }
        if (config.dividerPadding != null) {
            mDividerPadding = config.dividerPadding;
        }

        if (config.textsize != null) {
            mTextsize = sp2px(config.textsize);
        }
        if (config.textSelectColor != null) {
            mTextSelectColor = config.textSelectColor;
        }
        if (config.textUnselectColor != null) {
            mTextUnselectColor = config.textUnselectColor;
        }
        if (config.textBold != null) {
            mTextBold = config.textBold;
        }
        if (config.textAllCaps != null) {
            mTextAllCaps = config.textAllCaps;
        }

        if (config.tabSpaceEqual != null) {
            mTabSpaceEqual = config.tabSpaceEqual;
        }
        if (config.tabWidth != null) {
            mTabWidth = dp2px(config.tabWidth);
        }
        if (config.tabPadding != null) {
            mTabPadding = dp2px(config.tabPadding);
        }
        invalidate();
    }

    /* * 关联ViewPager */
    public void setViewPager(PageSlider vp) {
        if (vp == null || vp.getProvider() == null) {
            throw new IllegalStateException("ViewPager or ViewPager adapter can not be NULL !");
        }

        this.mViewPager = vp;

        this.mViewPager.removePageChangedListener(this);
        this.mViewPager.addPageChangedListener(this);
        notifyDataSetChanged();
    }

    /* * 关联ViewPager,用于不想在ViewPager适配器中设置titles数据的情况 */
    public void setViewPager(PageSlider vp, List<SamplePagerItem> titles) {
        if (vp == null || vp.getProvider() == null) {
            throw new IllegalStateException("ViewPager or ViewPager adapter can not be NULL !");
        }

        if (titles == null || titles.size() == 0) {
            throw new IllegalStateException("Titles can not be EMPTY !");
        }
        if (titles.size() != vp.getProvider().getCount()) {
            throw new IllegalStateException("Titles length must be the same as the page count !");
        }
        this.mViewPager = vp;
        mTables = titles;
//        Collections.addAll(mTitles, titles);
        try {
            this.mViewPager.removePageChangedListener(this);
        } catch (Exception e) {
            // Exception
        } catch (Error e) {
            // Error
        }
        this.mViewPager.addPageChangedListener(this);
        notifyDataSetChanged();
    }

    /* * 更新数据 */
    public void notifyDataSetChanged() {
        mTabsContainer.removeAllComponents();
        this.mTabCount = mTables == null ? mViewPager.getProvider().getCount() : mTables.size();
        Component tabView;
        for (int i = 0; i < mTabCount; i++) {
            tabView = LayoutScatter.getInstance(getContext()).parse(ResourceTable.Layout_layout_tab, null, false);
            CharSequence pageTitle = mTables == null ? mViewPager.getProvider().getPageTitle(i) : mTables.get(i).getTitle();
            addTab(i, pageTitle.toString(),mTables.get(i).getIconResIdUnCheck(), tabView);
        }

        updateTabStyles();
    }

    public void addNewTab(SamplePagerItem title) {
        Component tabView = LayoutScatter.getInstance(getContext()).parse(ResourceTable.Layout_layout_tab, null, false);
        if (mTables != null) {
            mTables.add(title);
        }

        CharSequence pageTitle =
                mTables == null ? mViewPager.getProvider().getPageTitle(mTabCount) : mTables.get(mTabCount).getTitle();
        addTab(mTabCount, pageTitle.toString(),mTables.get(mTabCount).getIconResIdUnCheck(), tabView);
        this.mTabCount = mTables == null ? mViewPager.getProvider().getCount() : mTables.size();

        updateTabStyles();
    }

    /* * 创建并添加tab */
    private void addTab(final int position, String title,int resId, Component tabView) {
        Text tvTabTitle = (Text) tabView.findComponentById(ResourceTable.Id_tv_tab_title);
        Image tvTabImage = (Image) tabView.findComponentById(ResourceTable.Id_tv_tab_image);
        if (tvTabTitle != null) {
            if (title != null) tvTabTitle.setText(title);
        }
        if(resId!=0){
            tvTabImage.setPixelMap(resId);
        }
        tabView.setClickedListener(
                new ClickedListener() {
                    @Override
                    public void onClick(Component component) {
                        int position = mTabsContainer.getChildIndex(component);
                        if (position != -1) {
                            if (mViewPager != null && mViewPager.getCurrentPage() != position) {
                                if (mSnapOnTabClick) {
                                    mViewPager.setCurrentPage(position, false);
                                } else {
                                    mViewPager.setCurrentPage(position, true);
                                }

                                if (mListener != null) {
                                    mListener.onTabSelect(position);
                                }
                            } else {
                                if (mListener != null) {
                                    mListener.onTabReselect(position);
                                }
                            }
                        }
                    }
                });
        /* * 每一个Tab的布局参数 */
        DirectionalLayout.LayoutConfig layoutConfig = new DirectionalLayout.LayoutConfig();
        if (mTabWidth > 0) {
            layoutConfig.width = (int) mTabWidth;
            layoutConfig.height = LayoutConfig.MATCH_PARENT;
        } else {
//            if (mTabSpaceEqual) {
                layoutConfig.width = LayoutConfig.MATCH_CONTENT;
                layoutConfig.height = LayoutConfig.MATCH_PARENT;
//            } else {
//                layoutConfig.width = LayoutConfig.MATCH_CONTENT;
//                layoutConfig.height = LayoutConfig.MATCH_PARENT;
//            }
        }
        mTabsContainer.addComponent(tabView, position, layoutConfig);
    }

    private void updateTabStyles() {
        for (int i = 0; i < mTabCount; i++) {
            Component v = mTabsContainer.getComponentAt(i);
            if(fonttype==FONTTYPE.OHOS){
                v.setBackground(new ShapeElement());
            }else {
                ShapeElement shapeElement=new ShapeElement();
                shapeElement.setRgbColor(new RgbColor(255,255,255,50));
                v.setBackground(shapeElement);
            }
            DirectionalLayout.LayoutConfig layoutConfig = (DirectionalLayout.LayoutConfig) v.getLayoutConfig();
            if (mTabWidth > 0) {
                layoutConfig.width = (int) mTabWidth;
                layoutConfig.height = LayoutConfig.MATCH_PARENT;
                v.setLayoutConfig(layoutConfig);
            }else {
                layoutConfig.width = LayoutConfig.MATCH_CONTENT;
                layoutConfig.height = LayoutConfig.MATCH_PARENT;
                v.setLayoutConfig(layoutConfig);
            }
            Text tvTabTitle = (Text) v.findComponentById(ResourceTable.Id_tv_tab_title);
            Image tvTabImage = (Image) v.findComponentById(ResourceTable.Id_tv_tab_image);
            if (tvTabTitle != null) {
                tvTabTitle.setTextColor(i == mCurrentTab ? new Color(mTextSelectColor) : new Color(mTextUnselectColor));
                tvTabTitle.setTextSize((int) (mTextsize));
                tvTabTitle.setPadding((int) mTabPadding, 0, (int) mTabPadding, 0);
                if (mTextAllCaps) {
                    tvTabTitle.setText(tvTabTitle.getText().toString().toUpperCase());
                }

                if (mTextBold == TEXT_BOLD_BOTH) {
                    tvTabTitle.setFont(Font.DEFAULT_BOLD);
                } else if (mTextBold == TEXT_BOLD_NONE) {
                    tvTabTitle.setFont(Font.DEFAULT);
                }
                tvTabTitle.setVisibility(HIDE);
            }
            if(tvTabImage!=null){
                tvTabImage.setPixelMap(i == mCurrentTab ?mTables.get(i).getIconResIdCheck():mTables.get(i).getIconResIdUnCheck());
                tvTabImage.setVisibility(HIDE);
            }
            switch (showtype){
                case Icon:
                    tvTabImage.setVisibility(VISIBLE);
                    tvTabTitle.setVisibility(HIDE);
                    break;
                case Title:
                    tvTabTitle.setVisibility(VISIBLE);
                    break;
                case IconAndTitle:
                    tvTabTitle.setVisibility(VISIBLE);
                    tvTabImage.setVisibility(VISIBLE);
                    break;
            }
        }
        invalidate();
    }

    @Override
    public void onPageSliding(int i, float v, int i1) {
        /**
         * position:当前View的位置
         * mCurrentPositionOffset:当前View的偏移量比例.[0,1)
         */
        if (i1 != 0) {
            this.mCurrentTab = i;
        } else {
            this.mCurrentTab = this.mTargetIndex;
        }
        if (v < 1) {
            this.mCurrentPositionOffset = v;
        } else {
            this.mCurrentPositionOffset = 0;
        }
        this.mCurrentOffset = i1;
        scrollToCurrentTab();
        invalidate();
    }

    @Override
    public void onPageSlideStateChanged(int i) {
        if(i == 0) {
            this.mCurrentTab = this.mTargetIndex;
            invalidate();
        }
    }

    @Override
    public void onPageChosen(int i) {
        this.mTargetIndex = i;
        updateTabSelection(i);
    }

    private void scrollToCurrentTab() {
        if (mTabCount <= 0) {
            return;
        }
        int offset = (int) (mCurrentPositionOffset * mTabsContainer.getComponentAt(mCurrentTab).getWidth());
        if (mCurrentOffset < 0) {
            offset = -offset;
        }
        int screenWidth =
                mContext.getResourceManager().getDeviceCapability().width
                        * mContext.getResourceManager().getDeviceCapability().screenDensity
                        / 160;
        int newScrollX = mLastScrollX;
        if (mCurrentPositionOffset > 0) {
            newScrollX =
                    mTabsContainer.getComponentAt(mCurrentTab).getLeft()
                            - (screenWidth - mTabsContainer.getComponentAt(mCurrentTab).getWidth()) / 2
                            + offset;
        } else {
            newScrollX =
                    mTabsContainer.getComponentAt(mCurrentTab).getLeft()
                            - (screenWidth - mTabsContainer.getComponentAt(mCurrentTab).getWidth()) / 2;
        }
        if (newScrollX != mLastScrollX) {
            mLastScrollX = newScrollX;
            /** scrollTo（int x,int y）:x,y代表的不是坐标点,而是偏移量
             *  x:表示离起始位置的x水平方向的偏移量
             *  y:表示离起始位置的y垂直方向的偏移量
             */
            if (scrollView != null) {
                if(scrollchoosetype==SCROLLCHOOSETYPE.Center){
                    scrollView.fluentScrollXTo(newScrollX);
                }else {
                    scrollView.fluentScrollXTo(0);
                }
            }
        }
    }

    private void updateTabSelection(int position) {
        for (int i = 0; i < mTabCount; ++i) {
            Component tabView = mTabsContainer.getComponentAt(i);
            final boolean isSelect = i == position;
            Text tabTitle = (Text) tabView.findComponentById(ResourceTable.Id_tv_tab_title);
            Image tvTabImage = (Image) tabView.findComponentById(ResourceTable.Id_tv_tab_image);
            if (tabTitle != null) {
                tabTitle.setTextColor(isSelect ? new Color(mTextSelectColor) : new Color(mTextUnselectColor));
                if (mTextBold == TEXT_BOLD_WHEN_SELECT) {
                    if (isSelect) {
                        tabTitle.setFont(Font.DEFAULT_BOLD);
                    } else {
                        tabTitle.setFont(Font.DEFAULT);
                    }
                }
            }
            if(tvTabImage!=null){
                tvTabImage.setPixelMap(isSelect?mTables.get(i).getIconResIdCheck():mTables.get(i).getIconResIdUnCheck());
            }
        }
    }

    private float margin;

    private void calcIndicatorRect() {
        Component currentTabView = mTabsContainer.getComponentAt(this.mCurrentTab);
        float left = currentTabView.getLeft();
        float right = currentTabView.getRight();
        if (mIndicatorStyle == STYLE_NORMAL && mIndicatorWidthEqualTitle) {
            Text tabTitle = (Text) currentTabView.findComponentById(ResourceTable.Id_tv_tab_title);
            mTextPaint.setTextSize((int) (mTextsize));
            float textWidth = mTextPaint.measureText(tabTitle.getText().toString());
            margin =culjian(culjian(right , left),textWidth)/ 2;
        }

        if (this.mCurrentTab < mTabCount) {
            Component nextTabView = mTabsContainer.getComponentAt(mTargetIndex);
            if (mTargetIndex == mCurrentTab) {
                if (mCurrentOffset > 0 && mCurrentTab + 1 < mTabCount) {
                    nextTabView = mTabsContainer.getComponentAt(mCurrentTab + 1);
                } else if (mCurrentOffset < 0 && mCurrentTab > 0) {
                    nextTabView = mTabsContainer.getComponentAt(mCurrentTab - 1);
                }
            }
            float nextTabLeft = nextTabView.getLeft();
            float nextTabRight = nextTabView.getRight();
            left =culjia(left , mCurrentPositionOffset * (culjian(nextTabLeft , currentTabView.getLeft()))) ;
            right = culjia(right , mCurrentPositionOffset * (culjian(nextTabRight , currentTabView.getRight())));
            if (mIndicatorStyle == STYLE_NORMAL && mIndicatorWidthEqualTitle) {
                Text nextTabTitle = (Text) nextTabView.findComponentById(ResourceTable.Id_tv_tab_title);
                mTextPaint.setTextSize((int) (mTextsize));
                float nextTextWidth = mTextPaint.measureText(nextTabTitle.getText().toString());
                float nextMargin =culjian(culjian(nextTabRight , nextTabLeft),nextTextWidth) / 2;
                margin = culjia(margin , mCurrentPositionOffset * (culjian(nextMargin , margin)));
            }
        }

        mIndicatorRect.left = (int) left;
        mIndicatorRect.right = (int) right;
        if (mIndicatorStyle == STYLE_NORMAL && mIndicatorWidthEqualTitle) {
            mIndicatorRect.left = (int) culjia(left , culjian(margin , 1f));
            mIndicatorRect.right = (int) culjian(right , culjian(margin , 1f));
        }

        mTabRect.left = (int) left;
        mTabRect.right = (int) right;

        if (mIndicatorWidth < 0) { // indicatorWidth小于0时,原jpardogo's PagerSlidingTabStrip
        } else { // indicatorWidth大于0时,圆角矩形以及三角形
            float indicatorLeft = culjia(currentTabView.getLeft() ,culjian (currentTabView.getWidth() , mIndicatorWidth)) / 2;
            if (this.mCurrentTab < mTabCount) {
                Component nextTab = mTabsContainer.getComponentAt(mTargetIndex);
                if (mTargetIndex == mCurrentTab) {
                    if (mCurrentOffset > 0 && mCurrentTab + 1 < mTabCount) {
                        nextTab = mTabsContainer.getComponentAt(mCurrentTab + 1);
                    } else if (mCurrentOffset < 0 && mCurrentTab > 0) {
                        nextTab = mTabsContainer.getComponentAt(mCurrentTab - 1);
                    }
                }
                float oldLeft = culjia(currentTabView.getLeft() , culjian(currentTabView.getWidth() , mIndicatorWidth)) / 2;
                float targetLeft =culjia(nextTab.getLeft() , culjian(nextTab.getWidth() , mIndicatorWidth))  / 2;
                indicatorLeft = culjia(oldLeft , mCurrentPositionOffset * culjian(targetLeft , oldLeft));
            }
            mIndicatorRect.left = (int) indicatorLeft;
            mIndicatorRect.right = (int) culjia(mIndicatorRect.left , mIndicatorWidth);
        }
    }

    private void onDraw() {
        addDrawTask(
                new DrawTask() {
                    @Override
                    public void onDraw(Component component, Canvas canvas) {
                        if (mTabCount <= 0) {
                            return;
                        }

                        int height = getHeight();
                        int paddingLeft = getPaddingLeft();
                        if (mDividerWidth > 0) {
                            mDividerPaint.setStrokeWidth(mDividerWidth);
                            mDividerPaint.setColor(new Color(mDividerColor));
                            for (int i = 0; i < mTabCount - 1; i++) {
                                Component tab = mTabsContainer.getComponentAt(i);
                                canvas.drawLine(
                                        new Point(culjia(paddingLeft , tab.getRight()), mDividerPadding),
                                        new Point(culjia(paddingLeft , tab.getRight()), culjian(height , mDividerPadding)),
                                        mDividerPaint);
                            }
                        }

                        if (mUnderlineHeight > 0) {
                            mRectPaint.setColor(new Color(mUnderlineColor));
                            if (mUnderlineGravity == GRAVITY_BOTTOM) {
                                canvas.drawRect(
                                        new RectFloat(
                                                paddingLeft,
                                                culjian(height , mUnderlineHeight),
                                                culjia(mTabsContainer.getWidth() , paddingLeft),
                                                height),
                                        mRectPaint);
                            } else {
                                canvas.drawRect(
                                        new RectFloat(
                                                paddingLeft,
                                                0,
                                                culjia(mTabsContainer.getWidth() , paddingLeft),
                                                mUnderlineHeight),
                                        mRectPaint);
                            }
                        }

                        calcIndicatorRect();
                        if (mIndicatorStyle == STYLE_TRIANGLE) {
                            if (mIndicatorHeight > 0) {
                                mTrianglePaint.setColor(new Color(mIndicatorColor));
                                mTrianglePath.reset();
                                mTrianglePath.moveTo(paddingLeft + mIndicatorRect.left, height);
                                mTrianglePath.lineTo(
                                        culjia(culjia(paddingLeft , mIndicatorRect.left / 2f) , mIndicatorRect.right / 2f),
                                        culjian(height , mIndicatorHeight));
                                mTrianglePath.lineTo(paddingLeft + mIndicatorRect.right, height);
                                mTrianglePath.close();
                                canvas.drawPath(mTrianglePath, mTrianglePaint);
                            }
                        } else if (mIndicatorStyle == STYLE_BLOCK) {
                            if (mIndicatorHeight < 0) {
                                mIndicatorHeight = culjian(culjian(height , mIndicatorMarginTop) , mIndicatorMarginBottom);
                            } else {
                            }

                            if (mIndicatorHeight > 0) {
                                if (mIndicatorCornerRadius < 0 || mIndicatorCornerRadius > mIndicatorHeight / 2) {
                                    mIndicatorCornerRadius = mIndicatorHeight / 2;
                                }

                                mIndicatorDrawable.setColor(new Color(mIndicatorColor));
                                canvas.drawRoundRect(
                                        new RectFloat(
                                                culjia(paddingLeft , culjia(mIndicatorMarginLeft , mIndicatorRect.left)),
                                                (int) mIndicatorMarginTop,
                                                culjian(culjia(paddingLeft , mIndicatorRect.right) , mIndicatorMarginRight),
                                                culjia(mIndicatorMarginTop , mIndicatorHeight)),
                                        mIndicatorCornerRadius,
                                        mIndicatorCornerRadius,
                                        mIndicatorDrawable);
                            }
                        } else {
                            if (mIndicatorHeight > 0) {
                                mIndicatorDrawable.setColor(new Color(mIndicatorColor));

                                if (mIndicatorGravity == GRAVITY_BOTTOM) {
                                    canvas.drawRoundRect(
                                            new RectFloat(
                                                    paddingLeft + (int) mIndicatorMarginLeft + mIndicatorRect.left,
                                                    height - (int) mIndicatorHeight - (int) mIndicatorMarginBottom,
                                                    paddingLeft + mIndicatorRect.right - (int) mIndicatorMarginRight,
                                                    height - (int) mIndicatorMarginBottom),
                                            mIndicatorCornerRadius,
                                            mIndicatorCornerRadius,
                                            mIndicatorDrawable);
                                } else {
                                    canvas.drawRoundRect(
                                            new RectFloat(
                                                    paddingLeft + (int) mIndicatorMarginLeft + mIndicatorRect.left,
                                                    (int) mIndicatorMarginTop,
                                                    paddingLeft + mIndicatorRect.right - (int) mIndicatorMarginRight,
                                                    (int) mIndicatorHeight + (int) mIndicatorMarginTop),
                                            mIndicatorCornerRadius,
                                            mIndicatorCornerRadius,
                                            mIndicatorDrawable);
                                }
                            }
                        }
                    }
                },
                DrawTask.BETWEEN_BACKGROUND_AND_CONTENT);
    }

    // setter and getter
    public void setCurrentTab(int currentTab) {
        this.mCurrentTab = currentTab;
        this.mTargetIndex = currentTab;
        mViewPager.setCurrentPage(currentTab);
    }

    public void setCurrentTab(int currentTab, boolean smoothScroll) {
        this.mCurrentTab = currentTab;
        this.mTargetIndex = currentTab;
        mViewPager.setCurrentPage(currentTab, smoothScroll);
    }

    public void setIndicatorStyle(int indicatorStyle) {
        this.mIndicatorStyle = indicatorStyle;
        invalidate();
    }

    public void setTabPadding(float tabPadding) {
        this.mTabPadding = dp2px(tabPadding);
        updateTabStyles();
    }

    public void setTabSpaceEqual(boolean tabSpaceEqual) {
        this.mTabSpaceEqual = tabSpaceEqual;
        updateTabStyles();
    }

    public void setTabWidth(float tabWidth) {
        this.mTabWidth = dp2px(tabWidth);
        updateTabStyles();
    }

    public void setIndicatorColor(int indicatorColor) {
        this.mIndicatorColor = indicatorColor;
        invalidate();
    }

    public void setIndicatorHeight(float indicatorHeight) {
        this.mIndicatorHeight = dp2px(indicatorHeight);
        invalidate();
    }

    public void setIndicatorWidth(float indicatorWidth) {
        this.mIndicatorWidth = dp2px(indicatorWidth);
        invalidate();
    }

    public void setIndicatorCornerRadius(float indicatorCornerRadius) {
        this.mIndicatorCornerRadius = dp2px(indicatorCornerRadius);
        invalidate();
    }

    public void setIndicatorGravity(int indicatorGravity) {
        this.mIndicatorGravity = indicatorGravity;
        invalidate();
    }

    public void setIndicatorMargin(
            float indicatorMarginLeft,
            float indicatorMarginTop,
            float indicatorMarginRight,
            float indicatorMarginBottom) {
        this.mIndicatorMarginLeft = dp2px(indicatorMarginLeft);
        this.mIndicatorMarginTop = dp2px(indicatorMarginTop);
        this.mIndicatorMarginRight = dp2px(indicatorMarginRight);
        this.mIndicatorMarginBottom = dp2px(indicatorMarginBottom);
        invalidate();
    }

    public void setIndicatorWidthEqualTitle(boolean indicatorWidthEqualTitle) {
        this.mIndicatorWidthEqualTitle = indicatorWidthEqualTitle;
        invalidate();
    }

    public void setUnderlineColor(int underlineColors) {
        this.mUnderlineColor = underlineColors;
        invalidate();
    }

    public void setUnderlineHeight(float underlineHeight) {
        this.mUnderlineHeight = dp2px(underlineHeight);
        invalidate();
    }

    public void setUnderlineGravity(int underlineGravity) {
        this.mUnderlineGravity = underlineGravity;
        invalidate();
    }

    public void setDividerColor(int dividerColor) {
        this.mDividerColor = dividerColor;
        invalidate();
    }

    public void setDividerWidth(float dividerWidth) {
        this.mDividerWidth = dp2px(dividerWidth);
        invalidate();
    }

    public void setDividerPadding(float dividerPadding) {
        this.mDividerPadding = dp2px(dividerPadding);
        invalidate();
    }

    public void setTextsize(float textsize) {
        this.mTextsize = sp2px(textsize);
        updateTabStyles();
    }

    public void setTextSelectColor(int textSelectColor) {
        this.mTextSelectColor = textSelectColor;
        updateTabStyles();
    }

    public void setTextUnselectColor(int textUnselectColor) {
        this.mTextUnselectColor = textUnselectColor;
        updateTabStyles();
    }

    public void setTextBold(int textBold) {
        this.mTextBold = textBold;
        updateTabStyles();
    }

    public void setTextAllCaps(boolean textAllCaps) {
        this.mTextAllCaps = textAllCaps;
        updateTabStyles();
    }

    public void setSnapOnTabClick(boolean snapOnTabClick) {
        mSnapOnTabClick = snapOnTabClick;
    }

    public int getTabCount() {
        return mTabCount;
    }

    public int getCurrentTab() {
        return mCurrentTab;
    }

    public int getIndicatorStyle() {
        return mIndicatorStyle;
    }

    public float getTabPadding() {
        return mTabPadding;
    }

    public boolean isTabSpaceEqual() {
        return mTabSpaceEqual;
    }

    public float getTabWidth() {
        return mTabWidth;
    }

    public int getIndicatorColor() {
        return mIndicatorColor;
    }

    public float getIndicatorHeight() {
        return mIndicatorHeight;
    }

    public float getIndicatorWidth() {
        return mIndicatorWidth;
    }

    public float getIndicatorCornerRadius() {
        return mIndicatorCornerRadius;
    }

    public float getIndicatorMarginLeft() {
        return mIndicatorMarginLeft;
    }

    public float getIndicatorMarginTop() {
        return mIndicatorMarginTop;
    }

    public float getIndicatorMarginRight() {
        return mIndicatorMarginRight;
    }

    public float getIndicatorMarginBottom() {
        return mIndicatorMarginBottom;
    }

    public int getUnderlineColor() {
        return mUnderlineColor;
    }

    public float getUnderlineHeight() {
        return mUnderlineHeight;
    }

    public int getDividerColor() {
        return mDividerColor;
    }

    public float getDividerWidth() {
        return mDividerWidth;
    }

    public float getDividerPadding() {
        return mDividerPadding;
    }

    public float getTextsize() {
        return mTextsize;
    }

    public int getTextSelectColor() {
        return mTextSelectColor;
    }

    public int getTextUnselectColor() {
        return mTextUnselectColor;
    }

    public int getTextBold() {
        return mTextBold;
    }

    public boolean isTextAllCaps() {
        return mTextAllCaps;
    }

    public Text getTitleView(int tab) {
        Component tabView = mTabsContainer.getComponentAt(tab);
        Text tvTabTitle = (Text) tabView.findComponentById(ResourceTable.Id_tv_tab_title);
        return tvTabTitle;
    }

    // setter and getter

    // show MsgTipView
    private Paint mTextPaint = new Paint();
    private PlainArray<Boolean> mInitSetMap = new PlainArray<>();

    /**
     * 显示未读消息
     *
     * @param position 显示tab位置
     * @param num      num小于等于0显示红点,num大于0显示数字
     */
    public void showMsg(int position, int num) {
        if (position >= mTabCount) {
            position = mTabCount - 1;
        }

        Component tabView = mTabsContainer.getComponentAt(position);
        MsgView tipView = (MsgView) tabView.findComponentById(ResourceTable.Id_rtv_msg_tip);
        if (tipView != null) {
            UnreadMsgUtils.show(tipView, num);

            if (mInitSetMap.get(position) != null
                    && mInitSetMap.get(position).isPresent()
                    && mInitSetMap.get(position).get()) {
                return;
            }

            setMsgMargin(position, 4, 2);
            mInitSetMap.put(position, true);
        }
    }

    /**
     * 显示未读红点
     *
     * @param position 显示tab位置
     */
    public void showDot(int position) {
        if (position >= mTabCount) {
            position = mTabCount - 1;
        }
        showMsg(position, 0);
    }

    /* * 隐藏未读消息 */
    public void hideMsg(int position) {
        if (position >= mTabCount) {
            position = mTabCount - 1;
        }

        Component tabView = mTabsContainer.getComponentAt(position);
        MsgView tipView = (MsgView) tabView.findComponentById(ResourceTable.Id_rtv_msg_tip);
        if (tipView != null) {
            tipView.setVisibility(Component.INVISIBLE);
        }
    }

    /* * 设置未读消息偏移,原点为文字的右上角.当控件高度固定,消息提示位置易控制,显示效果佳 */
    public void setMsgMargin(int position, float leftPadding, float bottomPadding) {
        if (position >= mTabCount) {
            position = mTabCount - 1;
        }
        Component tabView = mTabsContainer.getComponentAt(position);
        MsgView tipView = (MsgView) tabView.findComponentById(ResourceTable.Id_rtv_msg_tip);
        if (tipView != null) {
            Text tvTabTitle = (Text) tabView.findComponentById(ResourceTable.Id_tv_tab_title);
            mTextPaint.setTextSize((int) (mTextsize));
            float textWidth = mTextPaint.measureText(tvTabTitle.getText());
            LayoutConfig lp = (LayoutConfig) tipView.getLayoutConfig();
            lp.setMargins(
                    mTabWidth >= 0
                            ? (int) culjia(culjia(mTabWidth / 2f , textWidth / 2f) , dp2px(leftPadding))
                            : (int) culjia(culjia(mTabPadding , textWidth ), dp2px(leftPadding)),
                    getHeight() > 0 ? 10+dp2px(bottomPadding) : 0,
                    lp.getMarginRight(),
                    lp.getMarginBottom());
            tipView.setLayoutConfig(lp);
        }
    }

    /* * 当前类只提供了少许设置未读消息属性的方法,可以通过该方法获取MsgView对象从而各种设置 */
//    public MsgView getMsgView(int position) {
//        if (position >= mTabCount) {
//            position = mTabCount - 1;
//        }
//        Component tabView = mTabsContainer.getComponentAt(position);
//        MsgView tipView = (MsgView) tabView.findComponentById(ResourceTable.Id_rtv_msg_tip);
//        return tipView;
//    }

    private OnTabSelectListener mListener;

    public void setOnTabSelectListener(OnTabSelectListener listener) {
        this.mListener = listener;
    }

    static class InnerPagerAdapter extends PageSliderProvider {
        private ArrayList<AbilitySlice> fragments = new ArrayList<>();
        private String[] titles;

        public InnerPagerAdapter(ArrayList<AbilitySlice> fragments, String[] title) {
            this.fragments = fragments;
            this.titles = title;
        }

        @Override
        public int getCount() {
            return fragments.size();
        }

        @Override
        public Object createPageInContainer(ComponentContainer componentContainer, int i) {
            return null;
        }

        @Override
        public void destroyPageFromContainer(ComponentContainer componentContainer, int i, Object o) {}

        @Override
        public boolean isPageMatchToObject(Component component, Object o) {
            return false;
        }
    }

    private int dp2px(float dp) {
        return (int) (mContext.getResourceManager().getDeviceCapability().screenDensity / 160f * dp);
    }

    private int sp2px(float sp) {
        return (int) (mContext.getResourceManager().getDeviceCapability().screenDensity / 160f * sp);
    }
    public float culjia(double a,double b) {
        return (float) (a+b);
    }
    public float culjian(double a,double b) {
        return (float) (a-b);
    }
}
